package Friday.th4;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

//主类的框架
public class TankGame extends JFrame implements ActionListener {
    JMenuBar jmb;
    JMenu jm;
    JMenuItem jm1,jm2,jm3,jm4;
    StartPanel jp1;
    MyPanel jp2;
    public static void main(String[] args) {
        TankGame win=new TankGame();
    }
    public TankGame() {
        //菜单部分
        jmb=new JMenuBar();
        setJMenuBar(jmb);
        jm=new JMenu("游戏菜单");
        jmb.add(jm);
        jm1=new JMenuItem("开始新游戏");
        jm2=new JMenuItem("接着上局游戏");
        jm3=new JMenuItem("存盘退出");
        jm4=new JMenuItem("退出游戏");
        jm.add(jm1);
        jm.add(jm2);
        jm.add(jm3);
        jm.add(jm4);
        jm1.addActionListener(this);//为jm1注册监视器
        jp1=new StartPanel();//创建开始界面
        add(jp1);//添加初始界面
        jp2=new MyPanel();//创建游戏界面
        Thread st=new Thread(jp2);
        st.start();
        this.addKeyListener(jp2);
        //设置窗体属性
        setTitle("坦克大战");
        this.setSize(700,500);
        this.setLocation(300,300);
        this.setVisible(true);
        this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource()==jm1){
            remove(jp1);//移除开始界面
            add(jp2);//添加游戏界面并显示
            this.setVisible(true);
        }
    }
}
// 开始面板类StartPanel框架
class StartPanel extends JPanel {
    public StartPanel(){
        setLayout(new BorderLayout());
        setBackground(Color.BLACK);
        Font f = new Font("宋体",Font.PLAIN,25);
        JLabel jlb=new JLabel("Welcome to play Tank Game",JLabel.CENTER);
        jlb.setFont(f);//设置标签字体
        jlb.setForeground(Color.RED);//设置字体颜色
        add(jlb,BorderLayout.CENTER);//添加标签至开始面板
    }
    public void paint(Graphics g) {
        super.paint(g);
    }
}
//游戏面板类MyPanel框架
class MyPanel extends JPanel implements KeyListener,Runnable{
    public static int w1=15;
    public static int w2=30;
    public static int h1=80;
    public static int h2=50;
    Hero hero=null;//我方坦克
    Vector<Enemy> ets;
    //Enemy ets [];//敌人坦克
    int etsize=4;//敌人坦克数量
    //画出所有坦克
    public void paint(Graphics g){
        super.paint(g);
        //敌方坦克
        for(int i=0;i<etsize;i++){
            drawTank(ets.get(i).getX(), ets.get(i).getY(), ets.get(i).getDirect(),1,g);//画坦克
            for(int j=0;j<ets.get(i).ss.size();j++){
                if(ets.get(i).ss.get(j).isalive==true){
                    g.setColor(Color.yellow);
                    g.fillOval(ets.get(i).ss.get(j).x, ets.get(i).ss.get(j).y, 6, 6);
                }
            }
        }
        //我方坦克
        if(hero.isalive)drawTank(hero.getX(),hero.getY(),hero.getDirect(),0,g);
        //画子弹
        // 从ss中取出每一颗子弹，并画出
        for (int i = 0; i < hero.ss.size(); i++) {
            Shot shot = hero.ss.get(i);
            // 画出子弹
            if (shot.isalive == true) {
                g.setColor(Color.cyan);
                g.fillOval(shot.x, shot.y, 6, 6);
            }
            else {
                hero.ss.remove(i);i--;
            }
        }
    }
    //画出指定坦克
    public void drawTank(int tx,int ty,int direction,int type,Graphics g){
        //根据类型设置坦克颜色
        if(type==1)g.setColor(Color.YELLOW);
        else g.setColor(Color.cyan);
        //0->向上,1->向下
        if(direction==0||direction==1){
            g.fill3DRect(tx-(w1+w2/2),ty-h1/2,w1,h1,false);//左矩形
            g.fill3DRect(tx+w2/2,ty-h1/2,w1,h1,false);//右矩形
            g.fill3DRect(tx-w2/2,ty-h2/2,w2,h2,false);//中间矩形
            g.fillOval(tx-w2/2,ty-w2/2,w2,w2);//中间圆形
            //接下来根据坦克方向画炮杆
            if(direction==0){
                g.drawLine(tx,ty,tx,ty-h1/2);
            }
            else g.drawLine(tx,ty,tx,ty+h1/2);
        }
        else if(direction==2||direction==3){//2->向左,3->向右
            g.fill3DRect(tx-h1/2,ty-(w1+w2/2),h1,w1,false);//上矩形
            g.fill3DRect(tx-h1/2,ty+w2/2,h1,w1,false);//下矩形
            g.fill3DRect(tx-h2/2,ty-w2/2,h2,w2,false);//中间矩形
            g.fillOval(tx-w2/2,ty-w2/2,w2,w2);//中间圆形
            //接下来根据坦克方向画炮杆
            if(direction==2){
                g.drawLine(tx,ty,tx-h1/2,ty);
            }
            else g.drawLine(tx,ty,tx+h1/2,ty);
        }
    }
    public MyPanel(){
        setBackground(Color.BLACK);//设置背景色
        ets=new Vector<Enemy>();
        //创建坦克对象并给出其坐标
        for(int x=50,i=0;i<etsize;i++,x+=150){
            ets.add(new Enemy(x,50));
            Thread enemy=new Thread(ets.get(i));
            enemy.start();
        }
        hero=new Hero(160,300);
    }
    //面板线程的run方法
    public void run(){
        while (true){
            //面板每个100ms刷新一次
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //判断我方坦克子弹是否和某一敌坦相碰
            for(int i=0;i<etsize;i++){
                Shot shot=null;
                for(int j=0;j<hero.ss.size();j++){
                    shot=hero.ss.get(j);
                    if(!shot.isalive){hero.ss.remove(j);j--;continue;}//先判断子弹是否存在
                    if(hitTank(shot,ets.get(i))){//相碰
                        hero.ss.remove(j);
                        //shot=null;//消除子弹
                        ets.get(i).isalive=false;
                        ets.remove(i);//移除此敌坦
                        etsize--;//敌坦数量减一
                        break;
                    }
                }
            }
            //
            for(int i=0;i<ets.size()&&hero.isalive;i++){
                Enemy enemy=ets.get(i);
                for(int j=0;j<enemy.ss.size();j++){
                    Shot shot=enemy.ss.get(j);
                    if(!shot.isalive){
                        enemy.ss.remove(j);j--;continue;
                    }
                    if(hitTank(shot,hero)){
                        hero.isalive=false;
                        enemy.ss.remove(j);j--;
                        break;
                    }
                }
            }
            repaint();//刷新游戏面板
        }
    }
    //判断子弹和坦克相碰
    public boolean hitTank(Shot shot, Tank tank){
        int x1,x2,y1,y2;//x值下限,上限和y值的下限，上限
        if(tank.direct==0||tank.direct==1){
            y1=tank.y-h1/2;
            y2=tank.y+h1/2;
            x1=tank.x-w1-w2/2;
            x2=tank.x+w1+w2/2;
        }
        else {
            x1=tank.x-h1/2;
            x2=tank.x+h1/2;
            y1=tank.y-w1-w2/2;
            y2=tank.y+w1+w2/2;
        }
        //子弹位置如果在界限之内则相碰
        if(shot.x>=x1&&shot.x<=x2&&shot.y>=y1&&shot.y<=y2)return true;
        else return false;
    }
    @Override
    public void keyTyped(KeyEvent keyEvent) {
    }
    @Override
    public void keyPressed(KeyEvent keyEvent) {
        if(keyEvent.getKeyCode()==KeyEvent.VK_UP){//向上键
            if(hero.direct!=0){//如果一开始坦克没有向上先转变方向
                hero.direct=0;
                this.repaint();//刷新界面
            }
            else {
                hero.y-=hero.speed;//如果坦克初始方向向上那么以其速度向上移动
                this.repaint();//刷新界面
            }
        }//下同
        else if(keyEvent.getKeyCode()==KeyEvent.VK_DOWN){
            if(hero.direct!=1){
                hero.direct=1;
                this.repaint();
            }
            else {
                hero.y+=hero.speed;
                this.repaint();
            }
        }
        else if(keyEvent.getKeyCode()==KeyEvent.VK_LEFT){
            if(hero.direct!=2){
                hero.direct=2;
                this.repaint();
            }
            else {
                hero.x-=hero.speed;
                this.repaint();
            }
        }
        else if(keyEvent.getKeyCode()==KeyEvent.VK_RIGHT){
            if(hero.direct!=3){
                hero.direct=3;
                this.repaint();
            }
            else {
                hero.x+=hero.speed;
                this.repaint();
            }
        }
        else if(keyEvent.getKeyCode()==KeyEvent.VK_SPACE){
            hero.shoothers();
            this.repaint();
        }
    }
    @Override
    public void keyReleased(KeyEvent keyEvent) {
    }
}
//坦克类Tank框架
class Tank {
    int x = 0; //坦克坐标
    int y = 0;
    int direct; //坦克方向
    int speed = 5; //坦克速度
    Color color; //坦克颜色
    boolean isalive=true;
    public Tank(int x, int y,int direct) {
        this.x=x;this.y=y;this.direct=direct;
        if(direct==0)color=Color.cyan;
        else color=Color.YELLOW;
    }
    public int getX(){return x;};
    public int getY(){return y;};
    public int getDirect(){return direct;};
    public Color getColor(){return color;};
}
//我方坦克类Hero框架
class Hero extends Tank {
    Vector<Shot> ss=new Vector<Shot>();
    public Hero(int x, int y) {
        super(x,y,0);
    }
    //射击动作
    public void shoothers(){
        //坦克方向不同，子弹的相对位置不同
        if(direct==0)ss.add(new Shot(x-3,y-40,0));
        else if(direct==1)ss.add(new Shot(x-3,y+40,1));
        else if(direct==2)ss.add(new Shot(x-40,y-3,2));
        else if(direct==3)ss.add(new Shot(x+40,y-3,3));
        Thread shotother=new Thread(ss.lastElement());//使子弹线程就绪
        shotother.start();//执行发射子弹线程
    }
}
//敌方坦克类Enemy框架
class Enemy extends Tank implements Runnable{
    int time=0;
    Vector<Shot> ss=new Vector<Shot>();
    public Enemy(int x,int y) {
        super(x,y,1);
    }
    @Override
    public void run() {
        while(isalive){
            try {
                Thread.sleep(50);
            } catch (Exception e) {
                e.printStackTrace();
            }
            for(int i=0;i<10;i++){
                if(direct==0){
                    y-=speed;
                    if(y<40){y+=speed;}
                }
                else if(direct==1){
                    y+=speed;
                    if(y>600)y-=speed;
                }
                else if(direct==2){
                    x-=speed;
                    if(x<40)x+=speed;
                }
                else {
                    x+=speed;
                    if(x>1000)x-=speed;
                }
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            time++;
            if(time%2==0){
                if(isalive){
                    if(ss.size()<5){
                        shootothers();
                    }
                }
            }
            direct=(int)(Math.random()*4);
        }
    }
    public void shootothers(){
            if(direct==0)ss.add(new Shot(x-3,y-40,0));
            else if(direct==1)ss.add(new Shot(x-3,y+40,1));
            else if(direct==2)ss.add(new Shot(x-40,y-3,2));
            else if(direct==3)ss.add(new Shot(x+40,y-3,3));
            Thread shotother=new Thread(ss.lastElement());//使子弹线程就绪
            shotother.start();//执行发射子弹线
    }
}
//子弹类
class Shot implements Runnable {
    int x;
    int y;
    int direct;
    int speed=10;
    boolean isalive=true;//创建新的子弹默认true
    public Shot(int x, int y, int direct) {
        this.x=x;this.y=y;this.direct=direct;
    }
    //子单线程
    public void run(){
        while(true){
            try{
                Thread.sleep(50);
            }
            catch (Exception e){
                e.printStackTrace();
            }
            if(direct==0)y-=speed;
            else if(direct==1)y+=speed;
            else if(direct==2)x-=speed;
            else if(direct==3)x+=speed;
            //超过子弹有效显示范围则消失
            if(x<0||x>1000||y<0||y>1000){isalive=false;break;}
        }
    }
}
